<!--
 * @Descripttion: 课堂分析详情-教师行为-授课动作
 * @version: V1.0.0.1
 * @Author: zhaozhenzhuo
 * @Date: 2025-10-27 10:09:06
 * @LastEditors: zhaozhenzhuo
 * @LastEditTime: 2025-10-27 10:09:06
-->
<template>
	<div class="teacher-behavior-wrapper">
		<div class="module-title-wrapper">
			<p>授课动作</p>
			<img v-if="false" src="@/assets/images/lessonAnalysisDetails/text-edit-normal.png" />
		</div>
		<!-- 描述 -->
		<div class="detail">
			<p
				v-if="teacherBehaviorInfo && teacherBehaviorInfo.lessonCode"
				v-html="teacherBehaviorDesc"
			></p>
		</div>
		<div v-if="teacherBehaviorInfo && teacherBehaviorInfo.lessonCode" class="teacher-behavior-wrap">
			<div class="teacher-behavior-echarts-wrap"></div>
			<div class="list-wrap" :class="{ 'list-wrap-bottom': props.realBreakTimeArr?.length }">
				<div v-for="(item, index) in teacherBehaviorGeneralList" :key="index" class="item">
					<span class="num" :style="{ color: item.color }">{{ item.times }}次</span>
					<span>{{ item.duration }}</span>
				</div>
			</div>
		</div>
		<div v-else class="detail">
			<p>本堂课暂无教师授课动作。</p>
		</div>
	</div>
</template>

<script setup lang="ts">
import * as echarts from 'echarts';
import type {
	CustomSeriesRenderItemParams,
	CustomSeriesRenderItemAPI,
	ECElementEvent
} from 'echarts';
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue';
import { formatTime, formatSecToStr } from '@/assets/js/utils';
import type {
	CourseListItemType,
	AnalysisResultType,
	TeacherBehaviorInfoType,
	BehaviorsInfoItemType,
	TeacherBehaviorGeneralItemType,
	BehaviorDataType,
	NodeListType,
	PreviewInfoType,
	RealBreakTimeItemType
} from './TeacherBehavior.type';
import { getErrorMessage, getLessonTeacherBehaviorAPI } from '@/api/index';

const props = withDefaults(
	defineProps<{
		queryObj: {
			lessonInfo: CourseListItemType | null;
			aiScoreResult: AnalysisResultType | null;
			offsetTime: number;
			videoBeginTime: number;
		} | null;
		configInfo: Record<string, unknown> | null;
		realBreakTimeArr: RealBreakTimeItemType[] | null;
	}>(),
	{
		queryObj: null,
		configInfo: null,
		realBreakTimeArr: null
	}
);

const emit = defineEmits<{
	(e: 'behaviorData', data: BehaviorDataType): void;
	(e: 'changeVideoTime', time: number): void; // 切换视频时间
	(e: 'previewShow', info: PreviewInfoType): void;
}>();

const lessonInfo = computed(() => props.queryObj?.lessonInfo);
const aiScoreResult = computed(() => props.queryObj?.aiScoreResult);
const videoBeginTime = computed(() => props.queryObj?.videoBeginTime);

watch(
	() => props.queryObj,
	(val) => {
		if (val && val.aiScoreResult && val.lessonInfo) {
			nextTick(() => {
				getLessonTeacherBehavior();
			});
		}
	},
	{ immediate: true }
);

// 窗口大小与1920的比值
const rate = ref(
	(window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) / 1920
);

onMounted(() => {
	window.addEventListener('resize', resizeHandler);
});

onUnmounted(() => {
	window.removeEventListener('resize', resizeHandler);

	// 清理 DOM 事件监听器
	if (chartDom.value) {
		if (mousedownHandler.value) {
			chartDom.value.removeEventListener('mousedown', mousedownHandler.value);
			mousedownHandler.value = null;
		}
		if (clickHandler.value) {
			chartDom.value.removeEventListener('click', clickHandler.value);
			clickHandler.value = null;
		}
		chartDom.value = null;
	}

	// 清理 ECharts 实例
	if (behaviorChart.value) {
		behaviorChart.value.dispose();
		behaviorChart.value = null;
	}
});

const resizeHandler = () => {
	setTimeout(() => {
		rate.value =
			(window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) /
			1920;
		initTeacherBehaviorECharts();
	}, 300);
};

const configList = computed<NodeListType | null>(
	() =>
		((props.configInfo?.behaviorEchartsWrap as Record<string, unknown>)
			?.nodeList as NodeListType) || null
);

// 行为信息
const teacherBehaviorInfo = ref<TeacherBehaviorInfoType | null>(null);
// 图像开始时间
const startTime = ref<number>(0);
// 图像结束时间
const endTime = ref<number>(0);
// 行为统计结果列表
const teacherBehaviorGeneralList = ref<TeacherBehaviorGeneralItemType[]>([]);
// 描述
const teacherBehaviorDesc = ref<string>('');
// 获取教师行为数据
const getLessonTeacherBehavior = async () => {
	try {
		const data = await getLessonTeacherBehaviorAPI({
			lessonCode: lessonInfo.value?.code as string
		});

		startTime.value = aiScoreResult.value?.calBeginTime || 0;
		endTime.value = aiScoreResult.value?.calEndTime || 0;

		teacherBehaviorInfo.value = data;

		emit('behaviorData', {
			explainingTimes: teacherBehaviorInfo.value.explainingTimes,
			writingTimes: teacherBehaviorInfo.value.writingTimes,
			walkingTimes: teacherBehaviorInfo.value.walkingTimes
		});

		// 修改behaviorsInfo数据
		const _behaviorsInfo: BehaviorsInfoItemType[] = [];
		if (teacherBehaviorInfo.value.behaviorsInfo && teacherBehaviorInfo.value.behaviorsInfo.length) {
			teacherBehaviorInfo.value.behaviorsInfo.forEach((item) => {
				if (item.startTime * 1000 <= startTime.value && item.endTime * 1000 >= endTime.value) {
					_behaviorsInfo.push({
						behaviorType: item.behaviorType,
						imageUrl: item.imageUrl,
						startTime: startTime.value / 1000,
						endTime: endTime.value / 1000
					});
				} else if (
					item.startTime * 1000 <= startTime.value &&
					item.endTime * 1000 < endTime.value &&
					item.endTime * 1000 > startTime.value
				) {
					_behaviorsInfo.push({
						behaviorType: item.behaviorType,
						imageUrl: item.imageUrl,
						startTime: startTime.value / 1000,
						endTime: item.endTime
					});
				} else if (
					item.startTime * 1000 > startTime.value &&
					item.startTime * 1000 < endTime.value &&
					item.endTime * 1000 < endTime.value
				) {
					_behaviorsInfo.push(item);
				} else if (
					item.startTime * 1000 > startTime.value &&
					item.startTime * 1000 < endTime.value &&
					item.endTime * 1000 >= endTime.value
				) {
					_behaviorsInfo.push({
						behaviorType: item.behaviorType,
						imageUrl: item.imageUrl,
						startTime: item.startTime,
						endTime: endTime.value / 1000
					});
				}
			});
		}
		teacherBehaviorInfo.value.behaviorsInfo = _behaviorsInfo;

		// 计算每种行为出现的次数和时间
		let _explainingTimes = 0;
		let _explainingDuration = 0;
		let _writingTimes = 0;
		let _writingDuration = 0;
		let _walkingTimes = 0;
		let _walkingDuration = 0;
		let _standingTimes = 0;
		let _standingDuration = 0;
		let _sittingTimes = 0;
		let _sittingDuration = 0;
		let _bowingTimes = 0;
		let _bowingDuration = 0;
		let _leaningTimes = 0;
		let _leaningDuration = 0;
		let _usePhoneTimes = 0;
		let _usePhoneDuration = 0;
		let _answerphoneTimes = 0;
		let _answerphoneDuration = 0;
		teacherBehaviorInfo.value.behaviorsInfo.forEach((item) => {
			const _duration = item.endTime - item.startTime;
			if (
				item.behaviorType === 'explaining' &&
				(!configList.value || configList.value.explaining.show)
			) {
				_explainingTimes += 1;
				_explainingDuration += _duration;
			} else if (
				item.behaviorType === 'writing' &&
				(!configList.value || configList.value.writing.show)
			) {
				_writingTimes += 1;
				_writingDuration += _duration;
			} else if (
				item.behaviorType === 'walking' &&
				(!configList.value || configList.value.walking.show)
			) {
				_walkingTimes += 1;
				_walkingDuration += _duration;
			} else if (
				item.behaviorType === 'standing' &&
				(!configList.value || configList.value.standing.show)
			) {
				_standingTimes += 1;
				_standingDuration += _duration;
			} else if (
				item.behaviorType === 'sitting' &&
				(!configList.value || configList.value.sitting.show)
			) {
				_sittingTimes += 1;
				_sittingDuration += _duration;
			} else if (
				item.behaviorType === 'bowing' &&
				(!configList.value || configList.value.bowing.show)
			) {
				_bowingTimes += 1;
				_bowingDuration += _duration;
			} else if (
				item.behaviorType === 'leaning' &&
				(!configList.value || configList.value.leaning.show)
			) {
				_leaningTimes += 1;
				_leaningDuration += _duration;
			} else if (
				item.behaviorType === 'usephone' &&
				(!configList.value || configList.value.usephone.show)
			) {
				_usePhoneTimes += 1;
				_usePhoneDuration += _duration;
			} else if (
				item.behaviorType === 'answerphone' &&
				(!configList.value || configList.value.answerphone.show)
			) {
				_answerphoneTimes += 1;
				_answerphoneDuration += _duration;
			}
		});

		const _teacherBehaviorGeneralList = [];
		if (!configList.value || configList.value.explaining.show) {
			// 讲解指示
			_teacherBehaviorGeneralList.push({
				times: _explainingTimes,
				duration: formatSecToStr(_explainingDuration),
				color: '#89C7FC'
			});
		}
		if (!configList.value || configList.value.writing.show) {
			// 写板书
			_teacherBehaviorGeneralList.push({
				times: _writingTimes,
				duration: formatSecToStr(_writingDuration),
				color: '#66B3F4'
			});
		}
		if (!configList.value || configList.value.walking.show) {
			// 走动
			_teacherBehaviorGeneralList.push({
				times: _walkingTimes,
				duration: formatSecToStr(_walkingDuration),
				color: '#3E9AE8'
			});
		}
		if (!configList.value || configList.value.standing.show) {
			// 站立
			_teacherBehaviorGeneralList.push({
				times: _standingTimes,
				duration: formatSecToStr(_standingDuration),
				color: '#8AE4A3'
			});
		}
		if (!configList.value || configList.value.sitting.show) {
			// 端坐
			_teacherBehaviorGeneralList.push({
				times: _sittingTimes,
				duration: formatSecToStr(_sittingDuration),
				color: '#6BD689'
			});
		}
		if (!configList.value || configList.value.bowing.show) {
			// 低头
			_teacherBehaviorGeneralList.push({
				times: _bowingTimes,
				duration: formatSecToStr(_bowingDuration),
				color: '#F8A751'
			});
		}
		if (!configList.value || configList.value.leaning.show) {
			// 趴桌子
			_teacherBehaviorGeneralList.push({
				times: _leaningTimes,
				duration: formatSecToStr(_leaningDuration),
				color: '#F99135'
			});
		}
		if (!configList.value || configList.value.usephone.show) {
			// 使用手机
			_teacherBehaviorGeneralList.push({
				times: _usePhoneTimes,
				duration: formatSecToStr(_usePhoneDuration),
				color: '#F97811'
			});
		}
		if (!configList.value || configList.value.answerphone.show) {
			// 接打电话
			_teacherBehaviorGeneralList.push({
				times: _answerphoneTimes,
				duration: formatSecToStr(_answerphoneDuration),
				color: '#F97811'
			});
		}

		teacherBehaviorGeneralList.value = _teacherBehaviorGeneralList;

		const { writingTimes, explainingTimes, answerphoneTimes } = teacherBehaviorInfo.value;

		let explainingDesc = null;
		if (explainingTimes > 0) {
			explainingDesc = `讲解指示动作<span class="active">${explainingTimes}</span>次`;
		} else {
			explainingDesc = `讲课为主`;
		}

		let writingDesc = null;
		if (writingTimes > 0) {
			writingDesc = `书写板书<span class="active">${writingTimes}</span>次`;
		} else {
			writingDesc = `未书写板书`;
		}

		let answerphoneReportDesc = null;
		// 接打电话时间点列表
		const answerphoneList = teacherBehaviorInfo.value.behaviorsInfo
			.filter((item) => {
				return item.behaviorType === 'answerphone';
			})
			.map((item) => {
				return formatTime(item.startTime * 1000, 'HH:mm');
			});
		if (answerphoneTimes > 0 && answerphoneList.length) {
			answerphoneReportDesc = `老师在<span class="active">${answerphoneList.join(
				'、'
			)}</span>出现接打电话行为`;
		} else {
			answerphoneReportDesc = `老师未出现接打电话行为`;
		}

		teacherBehaviorDesc.value = `本堂课老师${explainingDesc}，${writingDesc}。${answerphoneReportDesc}。`;

		nextTick(() => {
			initTeacherBehaviorECharts();
		});
	} catch (err) {
		console.error(getErrorMessage(err));
	}
};

// 当前鼠标所在的小块序号
const currentIndex = ref<number>(-1);
// 当前鼠标所在位置的时间
const currentTime = ref<number | null>(null);
// echarts配置项
const echartsOption = ref<Record<string, unknown>>({});
// echarts对象
const behaviorChart = ref<echarts.ECharts | null>(null);
// 初始化图像
const initTeacherBehaviorECharts = () => {
	if (!teacherBehaviorInfo.value || !teacherBehaviorInfo.value.lessonCode) {
		return;
	}
	// 颜色数组
	const _statusItemStyleColorMap = {
		explaining: '#89C7FC',
		writing: '#66B3F4',
		walking: '#3E9AE8',
		standing: '#8AE4A3',
		sitting: '#6BD689',
		bowing: '#F8A751',
		leaning: '#F99135',
		usephone: '#F97811',
		answerphone: '#F97811'
	};
	// 文字描述数组
	const _statusItemNameMap = {
		explaining: '讲解指示',
		writing: '写板书',
		walking: '走动',
		standing: '站立',
		sitting: '端坐',
		bowing: '低头',
		leaning: '趴桌子',
		usephone: '使用手机',
		answerphone: '接打电话'
	};

	// 处理休息时间标记线数据
	const markLineData: Array<{ xAxis: number; label: { formatter: string } }> = [];
	if (props.realBreakTimeArr && props.realBreakTimeArr.length > 0) {
		props.realBreakTimeArr.forEach((item) => {
			// 开始休息的标记线
			if (item.startTime) {
				markLineData.push({
					xAxis: item.startTime,
					label: {
						formatter: '休息'
					}
				});
			}
			// 结束休息的标记线
			if (item.endTime) {
				markLineData.push({
					xAxis: item.endTime,
					label: {
						formatter: ''
					}
				});
			}
		});
	}

	const _behaviorsList = teacherBehaviorInfo.value.behaviorsInfo.map((item) => {
		return {
			value: [
				_statusItemNameMap[item.behaviorType as keyof typeof _statusItemNameMap], // y刻度下标
				item.startTime * 1000, // 开始时间
				item.endTime * 1000 // 结束时间
			],
			itemStyle: {
				color: _statusItemStyleColorMap[item.behaviorType as keyof typeof _statusItemStyleColorMap]
			}
		};
	});

	const yData = [];
	if (!configList.value || configList.value.explaining.show) {
		// 讲解指示
		yData.push('讲解指示');
	}
	if (!configList.value || configList.value.writing.show) {
		// 写板书
		yData.push('写板书');
	}
	if (!configList.value || configList.value.walking.show) {
		// 走动
		yData.push('走动');
	}
	if (!configList.value || configList.value.standing.show) {
		// 站立
		yData.push('站立');
	}
	if (!configList.value || configList.value.sitting.show) {
		// 端坐
		yData.push('端坐');
	}
	if (!configList.value || configList.value.bowing.show) {
		// 低头
		yData.push('低头');
	}
	if (!configList.value || configList.value.leaning.show) {
		// 趴桌子
		yData.push('趴桌子');
	}
	if (!configList.value || configList.value.usephone.show) {
		// 使用手机
		yData.push('使用手机');
	}
	if (!configList.value || configList.value.answerphone.show) {
		// 接打电话
		yData.push('接打电话');
	}

	const addZero = (n: number) => {
		if (n < 10) return `0${n}`;
		return n;
	};

	// 设置矩形
	const renderItem = (params: CustomSeriesRenderItemParams, api: CustomSeriesRenderItemAPI) => {
		const categoryIndex = api.value(0) as number;
		const start = api.coord([api.value(1), categoryIndex]) as number[];
		const end = api.coord([api.value(2), categoryIndex]) as number[];
		const sizeResult = api.size?.([0, 1]) as number[] | undefined;
		const height = (sizeResult?.[1] ?? 0) * 0.2;
		const coordSys = params.coordSys as unknown as {
			x: number;
			y: number;
			width: number;
			height: number;
		};
		// 如果是当前鼠标所在的块，则设置宽度为14px，从小块中心向两边放大
		const rectShape = echarts.graphic.clipRectByRect(
			{
				x:
					currentIndex.value === params.dataIndex
						? start[0] + (end[0] - start[0]) / 2 - 7
						: start[0],
				y: start[1] - height / 2 - 4, // 向上偏移3像素 确保居中
				// 将鼠标所在的小块宽度设置为14px，小块最小1px，小于1px的设置为1px
				/* eslint-disable no-nested-ternary */
				width:
					currentIndex.value === params.dataIndex
						? 14
						: end[0] - start[0] > 0 && end[0] - start[0] < 1
						? 1
						: end[0] - start[0],
				height: 16 * rate.value
			},
			{
				x: coordSys.x,
				y: coordSys.y,
				width: coordSys.width,
				height: coordSys.height
			}
		);
		// 保存一下每个小块的宽度
		const series = (echartsOption.value.series as Array<Record<string, unknown>>)?.[1];
		const data = series?.data as Array<Record<string, unknown>>;
		if (data?.[params.dataIndex]) {
			data[params.dataIndex].rectWidth = end[0] - start[0];
		}
		return (
			rectShape && {
				type: 'rect',
				transition: ['shape'],
				shape: rectShape,
				style: {
					fill: api.visual('color')
				}
			}
		);
	};
	// 清理旧的事件监听器
	if (chartDom.value) {
		if (mousedownHandler.value) {
			chartDom.value.removeEventListener('mousedown', mousedownHandler.value);
			mousedownHandler.value = null;
		}
		if (clickHandler.value) {
			chartDom.value.removeEventListener('click', clickHandler.value);
			clickHandler.value = null;
		}
	}

	// 绘制图像
	if (behaviorChart.value) {
		behaviorChart.value.dispose();
	}
	behaviorChart.value = echarts.init(
		document.querySelector('.teacher-behavior-echarts-wrap') as HTMLElement
	);
	echartsOption.value = {
		tooltip: {
			formatter: (params: { data: { value: number[] } }) => {
				return `${params.data.value[0]}：${formatTime(
					params.data.value[1],
					'YYYY-MM-DD HH:mm:ss'
				)}&nbsp;&nbsp;&nbsp;${formatTime(params.data.value[2], 'YYYY-MM-DD HH:mm:ss')}`;
			},
			textStyle: {
				fontFamily: 'Alibaba PuHuiTi',
				fontWeight: 'bold'
			}
		},
		backgroundColor: '#f6f9fb',
		grid: {
			top: 20 * rate.value,
			bottom: props.realBreakTimeArr?.length ? 25 * rate.value : 20 * rate.value, // 增加底部空间，为markLine标签留出位置
			left: '2%',
			right: 185 * rate.value,
			containLabel: true
		},
		xAxis: {
			type: 'time',
			min: startTime.value,
			max: endTime.value,
			axisLine: {
				show: true,
				lineStyle: {
					color: '#BDC7D4'
				}
			},
			axisLabel: {
				margin: 8 * rate.value,
				color: '#666666',
				fontSize: 14 * rate.value,
				fontWeight: 400,
				fontFamily: 'Alibaba PuHuiTi',
				formatter: (val: string) => {
					const d = new Date(val);
					return `${addZero(d.getHours())}:${addZero(d.getMinutes())}`;
				}
			},
			// 显示网格线
			splitLine: {
				show: true,
				lineStyle: {
					color: '#BDC7D4',
					type: 'dashed'
				},
				z: 2
			},
			axisPointer: {
				show: true,
				triggerTooltip: false,
				lineStyle: {
					color: '#0092FF'
				},
				label: {
					show: true,
					// margin: -700 * _rate,
					fontSize: 14 * rate.value,
					fontWeight: 400,
					fontFamily: 'Alibaba PuHuiTi',
					backgroundColor: '#807d8b',
					formatter: (params: { value: number }) => {
						// 保存一下当前的时间
						currentTime.value = params.value;
						const d = new Date(params.value);
						return `${addZero(d.getHours())}:${addZero(d.getMinutes())}:${addZero(d.getSeconds())}`;
					}
				}
			}
		},
		yAxis: {
			type: 'category',
			data: yData,
			inverse: true,
			axisLine: {
				show: true,
				lineStyle: {
					color: '#BDC7D4'
				}
			},
			axisLabel: {
				fontSize: 14 * rate.value,
				fontWeight: 400,
				fontFamily: 'Alibaba PuHuiTi',
				color: (value?: string | number, index?: number) => {
					const colorList = [];
					if (!configList.value || configList.value.explaining.show) {
						// 讲解指示
						colorList.push('#89C7FC');
					}
					if (!configList.value || configList.value.writing.show) {
						// 写板书
						colorList.push('#66B3F4');
					}
					if (!configList.value || configList.value.walking.show) {
						// 走动
						colorList.push('#2D95ED');
					}
					if (!configList.value || configList.value.standing.show) {
						// 站立
						colorList.push('#8AE4A3');
					}
					if (!configList.value || configList.value.sitting.show) {
						// 端坐
						colorList.push('#6BD689');
					}
					if (!configList.value || configList.value.bowing.show) {
						// 低头
						colorList.push('#F8A751');
					}
					if (!configList.value || configList.value.leaning.show) {
						// 趴桌子
						colorList.push('#F99135');
					}
					if (!configList.value || configList.value.usephone.show) {
						// 使用手机
						colorList.push('#F97811');
					}
					if (!configList.value || configList.value.answerphone.show) {
						// 接打电话
						colorList.push('#F97811');
					}
					return colorList[index ?? 0];
				}
			},
			axisTick: {
				show: false
			}
		},
		series: [
			{
				type: 'bar',
				name: '测试用于打开滚动条'
			},
			{
				type: 'custom',
				// 数据堆叠（成块显示）
				stack: 'Total',
				renderItem,
				encode: {
					x: [],
					y: [0]
				},
				data: _behaviorsList
			},
			// 辅助系列用于显示休息时间标记线
			{
				type: 'line',
				name: '休息时间标记',
				silent: true,
				data: [], // 不需要实际数据点
				markLine: {
					silent: false, // 允许触发事件
					symbol: 'none', // 不显示箭头
					label: {
						show: true,
						position: 'end', // 标签显示在线的末端（底部）
						fontSize: 12 * rate.value,
						color: '#22AC38',
						fontFamily: 'Alibaba PuHuiTi',
						fontWeight: 'bold',
						distance: [0, 25 * rate.value] // [水平偏移, 垂直偏移] 增加垂直距离，避免与x轴label重叠
					},
					lineStyle: {
						color: 'rgba(34, 172, 56, 0.3)', // 半透明绿色标记线
						type: 'solid',
						width: 2 * rate.value
					},
					data: markLineData,
					animation: false
				}
			}
		]
	};
	behaviorChart.value.setOption(echartsOption.value);

	bindClickEvent();
};

// 当前是否点击的是小块，true：点击小块 false：点击空白处
const isClickRect = ref<boolean>(false);
// 节流标识
const flag = ref<boolean>(false);
// 图片信息
const picInfo = ref<PreviewInfoType | null>(null);
// 保存 chartDom 引用和事件处理函数引用，用于清理
const chartDom = ref<HTMLDivElement | null>(null);
const mousedownHandler = ref<((e: MouseEvent) => void) | null>(null);
const clickHandler = ref<((e: MouseEvent) => void) | null>(null);
// 绑定点击事件
const bindClickEvent = () => {
	/* 点击事件 */
	chartDom.value = document.querySelector('.teacher-behavior-echarts-wrap');
	if (chartDom.value) {
		// chart绑定鼠标按下事件
		let _offsetX = 0;
		let _offsetY = 0;

		// 创建并保存 mousedown 事件处理函数
		mousedownHandler.value = (e: MouseEvent) => {
			// 记录一下按下时的坐标
			_offsetX = e.offsetX;
			_offsetY = e.offsetY;
		};

		// 创建并保存 click 事件处理函数
		clickHandler.value = (e: MouseEvent) => {
			// 如果起始点和结束点不在一个位置，就是拖动，不触发点击事件，具体判断条件x、y坐标偏移不超过5px 或 点击的是小块不触发下面的事件
			if (
				e.offsetX - _offsetX > 5 ||
				e.offsetX - _offsetX < -5 ||
				e.offsetY - _offsetY > 5 ||
				e.offsetY - _offsetY < -5 ||
				isClickRect.value
			) {
				return;
			}
			// 获取像素数组
			const _pixelArr: number[] = [e.offsetX, e.offsetY];
			// 如果点击了图像以外的部分，就不触发下面的事件
			if (!behaviorChart.value?.containPixel('grid', _pixelArr)) {
				return;
			}
			// 设置视频时间
			const _currentTime =
				(currentTime.value || 0) - (videoBeginTime.value || 0) > 0
					? ((currentTime.value || 0) - (videoBeginTime.value || 0)) / 1000
					: 0;

			// 通知视频组件弹框
			emit('changeVideoTime', _currentTime);
		};

		// 绑定事件
		chartDom.value.addEventListener('mousedown', mousedownHandler.value);
		chartDom.value.addEventListener('click', clickHandler.value);
	}

	// 绑定echarts事件
	behaviorChart.value?.on('mouseover', (params: { dataIndex: number }) => {
		// 只有宽度小于14px的块才走事件
		const series = (echartsOption.value.series as Array<Record<string, unknown>>)?.[1];
		const data = series?.data as Array<Record<string, unknown>>;
		if (
			data?.[params.dataIndex]?.rectWidth &&
			(data[params.dataIndex].rectWidth as number) <= 14 &&
			!flag.value
		) {
			flag.value = true;
			setTimeout(() => {
				flag.value = false;
			}, 200);
			currentIndex.value = params.dataIndex;
			behaviorChart.value?.setOption(echartsOption.value);
		}
	});
	behaviorChart.value?.on('mouseout', () => {
		// 鼠标移出恢复
		if (currentIndex.value !== -1) {
			currentIndex.value = -1;
			behaviorChart.value?.setOption(echartsOption.value);
		}
	});
	behaviorChart.value?.on('mousemove', (params: { dataIndex: number }) => {
		// 只有宽度小于14px的块才走事件，防止鼠标移入时不满足条件导致的块大小没有变化的问题
		const series = (echartsOption.value.series as Array<Record<string, unknown>>)?.[1];
		const data = series?.data as Array<Record<string, unknown>>;
		if (
			data?.[params.dataIndex]?.rectWidth &&
			(data[params.dataIndex].rectWidth as number) <= 14 &&
			currentIndex.value !== params.dataIndex &&
			!flag.value
		) {
			flag.value = true;
			setTimeout(() => {
				flag.value = false;
			}, 200);
			currentIndex.value = params.dataIndex;
			behaviorChart.value?.setOption(echartsOption.value);
		}
	});
	behaviorChart.value?.on('mousedown', () => {
		// 当前点击的是小块
		isClickRect.value = true;
	});
	behaviorChart.value?.on('click', (params: ECElementEvent) => {
		const _startTime =
			(teacherBehaviorInfo.value?.behaviorsInfo?.[params.dataIndex]?.startTime as number) * 1000 ||
			0;
		// 设置视频时间
		const _currentTime =
			_startTime - (videoBeginTime.value || 0) > 0
				? (_startTime - (videoBeginTime.value || 0)) / 1000
				: 0;

		picInfo.value = {
			transFileUrl: teacherBehaviorInfo.value?.behaviorsInfo[params.dataIndex].imageUrl
				? changeImageURl(teacherBehaviorInfo.value?.behaviorsInfo[params.dataIndex].imageUrl)
				: '',
			name: `授课行为分析（${params.name || '未知行为'}）`,
			type: 1,
			videoTime: _currentTime - 1, // 这段行为开始时间对应的视频时间
			analysisType: 1 // 1:老师 2:学生
		};
		emit('previewShow', picInfo.value);
		// 点击事件完成恢复初始值
		setTimeout(() => {
			isClickRect.value = false;
		}, 50);
	});
};

// 拦截更改图片地址
const changeImageURl = (url: string) => {
	if (url.includes('stream?')) {
		return url;
	}
	return `${window.location.protocol}//${window.location.host}/stream?srcUrl=${url}`;
};
</script>

<style lang="scss" scoped>
.teacher-behavior-wrapper {
	margin-top: 1.6rem;

	.teacher-behavior-wrap {
		position: relative;
		height: 36rem;
		.teacher-behavior-echarts-wrap {
			width: 100%;
			height: 100%;
		}
		.list-wrap {
			position: absolute;
			right: 2rem;
			top: 2rem;
			display: flex;
			flex-direction: column;
			justify-content: space-around;
			width: 15rem;
			height: calc(100% - 2rem - 2rem - 1.4rem - 8px);
			white-space: nowrap;
			font-size: $font-size-small-1;

			&.list-wrap-bottom {
				height: calc(100% - 2rem - 2rem - 1.4rem - 8px - 0.5rem);
			}

			.item {
				display: flex;
				justify-content: space-between;
			}
		}
	}
}
</style>
